package org.demo.test.socket.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.handler.codec.serialization.ObjectEncoderOutputStream;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.apache.log4j.Logger;
import org.demo.test.socket.User;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.ThreadFactory;

public class NettySocketClient {

	public static void main(String[] args) {
		// 主服务启动器
		Bootstrap client = new Bootstrap();
		// boss线程池
		EventLoopGroup bossLoopGroup = new NioEventLoopGroup(1);
		client.group(bossLoopGroup);
		
		// 设置服务的通道类型
		client.channel(NioSocketChannel.class);
		client.handler(new ChannelInitializer<NioSocketChannel>() {
			@Override
			protected void initChannel(NioSocketChannel ch) throws Exception {
				ch.pipeline().addLast(new MessageToMessageEncoder<User>() {
					@Override
					protected void encode(ChannelHandlerContext ctx, User msg, List<Object> out) throws Exception {
						System.out.println("encode:"+msg);
						ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
						ObjectEncoderOutputStream objectEncoderOutputStream = new ObjectEncoderOutputStream(byteArrayOutputStream);
						objectEncoderOutputStream.writeObject(msg);
//						out.add(ByteBufUtil.encodeString(ctx.alloc(), Byte.wrap(byteArrayOutputStream.toByteArray()), Charset.defaultCharset()));
						out.add(Unpooled.wrappedBuffer(byteArrayOutputStream.toByteArray()));
					}
				});
				ch.pipeline().addLast(new TCPClientHandler());
//				ch.pipeline().addLast(new ByteArrayDecoder());
//				ch.pipeline().addLast(new ByteArrayEncoder());
				ch.pipeline().addLast(new MessageToMessageDecoder<User>() {
					@Override
					protected void decode(ChannelHandlerContext ctx, User msg, List<Object> out) throws Exception {
						System.out.println("decode:"+msg);
						out.add(msg);
					}
				});
			}
		});
		
		// 设置服务器绑定的端口IP
//		serverBootstrap.option(ChannelOption.SO_BACKLOG, 123);
//		serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
//		serverBootstrap.bind("0.0.0.0", 6666);
		//serverBootstrap.bind("0.0.0.0", 6667);

		//连接服务器
		try {
			ChannelFuture future = client.connect("127.0.0.1", 6666).sync();
			//发送数据给服务器
			User user = new User();
			user.setUserName("sssss");
			user.setPassword("123123123");
			future.channel().writeAndFlush(user);
			//当通道关闭了，就继续往下走
//			future.channel().closeFuture().sync();

			//接收服务端返回的数据
//			AttributeKey<String> key = AttributeKey.valueOf("ServerData");
//			Object result = future.channel().attr(key).get();
 			System.out.println("result.toString()");
			while (true){

			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class TCPClientHandler extends ChannelInboundHandlerAdapter{

	Logger logger = Logger.getLogger(TCPClientHandler.class);
	
	private static AttributeKey<StringBuffer> content = AttributeKey.valueOf("content");
	
	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		logger.info("channelRegistered 注册!");
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		logger.info("channelRegistered 激活!");
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		// TODO Auto-generated method stub
		super.channelInactive(ctx);
	}

	/*@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		ByteBuf bb = (ByteBuf)msg;
		try{
			StringBuffer sb = new StringBuffer();
			while(bb.isReadable()){
				sb.append((char)bb.readByte());
			}
			StringBuffer con = ctx.attr(content).get();
			if(con == null){
				con = new StringBuffer();
				ctx.attr(content).set(con);
			}
			con.append(sb);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			bb.release();
		}
	}*/

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		System.out.println(msg);
		User bb = (User)msg;
		System.out.println(bb);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		// TODO Auto-generated method stub
		super.channelReadComplete(ctx);
	}
	
}
